{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Controlled-Z 门\n",
    "\n",
    "*版权所有 (c) 2021 百度量子计算研究所，保留所有权利。*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 内容概要\n",
    "在本教程中，我们将使用量脉云服务实现一个 Controlled-Z 门。本教程的概要如下：\n",
    "\n",
    "- 背景介绍\n",
    "- 准备工作\n",
    "- 构造哈密顿量\n",
    "- 通过量脉云服务生成与优化脉冲序列\n",
    "- 总结"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 背景介绍\n",
    "\n",
    "Controlled-Z 门（CZ 门）是一个双量子比特门：当控制量子比特与目标量子比特的量子态为 $|11\\rangle$ 时，CZ 门会给目标量子比特增加一个 $e^{i\\pi}$ 的相位。CZ 门的物理实现是利用磁通来调节量子比特的本征频率：缓慢增加磁通至 $\\phi_{\\rm cz}$，等待一定的时间让系统自由演化并且积累一个相位因子 $\\pi$，随后将磁通恢复到 0 \\[1\\]。由于更强的电感耦合，CZ 门相比 cross-resonance 门能实现更快的双量子比特控制。\n",
    "\n",
    "$U_{\\rm CZ}$ 的矩阵表示是:\n",
    "$$\n",
    "U_{\\rm CZ} = |0\\rangle\\langle 0| \\otimes I + |1\\rangle\\langle1| \\otimes \\hat{\\sigma}^z = \\begin{bmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 0 & 0 & -1 \\end{bmatrix}. \n",
    "$$  \n",
    "\n",
    "由关系式 $H\\hat{\\sigma}^zH=\\hat{\\sigma}^x$ 可知，CNOT 门可以通过一个 CZ 和两个 Hadamard 门实现\\[1\\]。\n",
    "\n",
    "![cnot](figures/cz-cnot.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 准备工作\n",
    "\n",
    "成功安装量脉后，您可以按照本教程运行下面的量脉的程序。要运行此教程，您需要从量脉（Quanlse）和其它常用的 Python 库导入以下包："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import Hamiltonian-related modules \n",
    "from Quanlse.QHamiltonian import QHamiltonian as QHam\n",
    "from Quanlse.QOperator import duff, number\n",
    "\n",
    "# Import the optimizer for controlled-z gate\n",
    "from Quanlse.remoteOptimizer import remoteOptimizeCz\n",
    "\n",
    "# Import tools for result analysis\n",
    "from Quanlse.Utils.Functions import project\n",
    "\n",
    "# Import numpy and math\n",
    "from numpy import round\n",
    "from math import pi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 构造哈密顿量\n",
    "\n",
    "\n",
    "在我们的模型中，我们引入第三个能级来考虑双量子比特系统的能量泄漏。我们要定义的系统哈密顿量是：\n",
    "\n",
    "$$\n",
    "\\hat{H}_{\\rm sys}(t) = (\\omega_{\\rm q0}-\\omega_{\\rm d0})\\hat{a}_0^\\dagger \\hat{a}_0+(\\omega_{\\rm q1}-\\omega_{\\rm d0}) \\hat{a}_1^\\dagger \\hat{a}_1+\\frac{\\alpha_0}{2}\\hat{a}_0^{\\dagger}\\hat{a}_0^\\dagger\\hat{a}_0\\hat{a}_0 + \\frac{\\alpha_1}{2}\\hat{a}_1^\\dagger\\hat{a}_1^\\dagger\\hat{a}_1\\hat{a}_1 + \\frac{g}{2}(\\hat{a}_0\\hat{a}_1^\\dagger+\\hat{a}_0^\\dagger\\hat{a}_1) + \\frac{A_0^z(t)}{2}\\hat{a}_0^\\dagger \\hat{a}_0,\n",
    "$$\n",
    "\n",
    "其中，$\\hat{a}_i^\\dagger$、$\\hat{a}_i$ 是量子比特 $q_i$ ($i$=0, 1) 的产生和湮灭算符。有关硬件结构的信息由以下参数确定：量子比特频率 $\\omega_{qi}$、驱动频率 $\\omega_{di}$、非谐性 $\\alpha_i$ 和耦合强度 $g$。\n",
    "\n",
    "在量脉中，我们将下面的三项相加来构造系统哈密顿量：\n",
    "\n",
    "$$\n",
    "\\hat{H}_{\\rm sys}(t) = \\hat{H}_{\\rm drift} + \\hat{H}_{\\rm coup} + \\hat{H}_{\\rm ctrl}(t). \n",
    "$$\n",
    "\n",
    "我们首先定义必要的函数参数，包括采样周期、量子比特的数量以及系统的能级。然后我们通过传入刚刚定义的参数来使用 `QHamiltonian()` 函数，以初始化包含哈密顿量信息的字典。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sampling period\n",
    "dt = 1.0\n",
    "\n",
    "# Number of qubits\n",
    "qubits = 2\n",
    "\n",
    "# System energy levels\n",
    "level = 3\n",
    "\n",
    "# Initilize the Hamiltonian\n",
    "ham = QHam(subSysNum=qubits, sysLevel=level, dt=dt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "初始化哈密顿量的字典之后，我们可以向该字典添加不同的项。我们首先定义硬件参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Specify the parameters of the hardware\n",
    "qubitArgs = {\n",
    "    \"coupling\": 0.0277 * (2 * pi),  # Coupling of Q0 and Q1\n",
    "    \"qubit_freq0\": 5.805 * (2 * pi),  # Frequency of Q0\n",
    "    \"qubit_freq1\": 5.205 * (2 * pi),  # Frequency of Q1\n",
    "    \"drive_freq0\": 5.205 * (2 * pi),  # Drive frequency on Q0 (rotating frame)\n",
    "    \"drive_freq1\": 5.205 * (2 * pi),  # Drive frequency on Q1 (rotating frame)\n",
    "    \"qubit_anharm0\": -0.217 * (2 * pi),  # Anharmonicity of Q0\n",
    "    \"qubit_anharm1\": -0.226 * (2 * pi)  # Anharmonicity of Q1\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来，我们在哈密顿量中加入漂移项。漂移哈密顿量 $\\hat{H}_{\\rm drift}$ 的形式如下：\n",
    "\n",
    "$$\n",
    "\\hat{H}_{\\rm drift} = (\\omega_{\\rm q0}-\\omega_{\\rm d0})\\hat{n}_0+(\\omega_{\\rm q1}-\\omega_{\\rm d0})\\hat{n}_1+\\frac{\\alpha_0}{2}\\hat{a}_0^\\dagger\\hat{a}_0^\\dagger\\hat{a}_0\\hat{a}_0+\\frac{\\alpha_1}{2}\\hat{a}_1^\\dagger\\hat{a}_1^\\dagger\\hat{a}_1\\hat{a}_1 .\n",
    "$$\n",
    "\n",
    "这里，$\\hat{n}_i=\\hat{a}^\\dagger_i \\hat{a}_i$ 是量子比特 $q_i$ 的粒子数算符。在量脉中，我们可以使用 `addDrift()` 函数来添加漂移项。该函数的输入参数有哈密顿量的字典、用户定义的名称、该项作用的量子比特的列表、相应的算符和系数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Add the drift term(s)\n",
    "for qu in range(2):\n",
    "    # Add the detuning term(s)\n",
    "    ham.addDrift(number, qu, (qubitArgs[f\"qubit_freq{qu}\"] - qubitArgs[f\"drive_freq{qu}\"]))\n",
    "    # Add the anharmonicity term(s)\n",
    "    ham.addDrift(duff, qu, qubitArgs[f\"qubit_anharm{qu}\"] / 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在我们加上耦合项 $\\hat{H}_{\\rm coup}$，其形式是：\n",
    "$$\n",
    "\\hat{H}_{\\rm coup} = \\frac{g}{2}(\\hat{a}_0\\hat{a}_1^\\dagger+\\hat{a}_0^\\dagger\\hat{a}_1) .\n",
    "$$\n",
    "\n",
    "耦合哈密顿量可以通过函数 `addCoupling()` 来添加。函数输入参数包括哈密顿量的字典，用户定义的名称，此项作用的量子比特的列表，以及耦合强度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Add coupling term\n",
    "ham.addCoupling([0, 1], qubitArgs[\"coupling\"] / 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "需要注意的是，量脉的优化函数会自动添加控制项：\n",
    "\n",
    "$$ \n",
    "\\hat{H}_{\\rm ctrl}(t) = \\frac{A_0^z(t)}{2}\\hat{a}_0^\\dagger \\hat{a}_0, \n",
    "$$\n",
    "\n",
    "所以我们不需要手动添加这项。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "系统的哈密顿量构造完成后，我们可以进行量子系统的模拟。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通过量脉云服务生成和优化脉冲"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在本地设备上处理优化过程通常需要很长时间，而我们提供的云服务可以显著加速此过程。在使用量脉云服务之前，用户需要从 http://quantum-hub.baidu.com 获取 token。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import tools to get access to cloud service\n",
    "from Quanlse import Define\n",
    "\n",
    "# To use remoteOptimizerCz() on cloud, paste your token (a string) here\n",
    "Define.hubToken = ''"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在本例中，我们可以使用 `remoteOptimizeCz()` 生成和优化控制脉冲以达到指定的 `targetInfidelity`。要使用这个函数，用户需要指定一个哈密顿量的字典、振幅的界、门的持续时间、最大迭代次数和目标失真度。此函数返回一个哈密顿量字典和失真度的局部极小值。`aBound` 设定了我们脉冲强度的界限，而更大的界限会意味着更大的搜索空间。因此，我们可以增加迭代次数以获取更好的结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aBound=(-5, -1)  # The bound of the pulse's strength \n",
    "gateJob, infidelity = remoteOptimizeCz(ham, aBound=aBound, tg=40, maxIter=5, targetInfidelity=0.005)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "我们现在可以获取优化后的脉冲以及失真度。在这个教程中，我们将用于评估量子门性能的失真度定义为：${\\rm infid} = 1 - \\frac{1}{d}\\left|{\\rm Tr}[U^\\dagger_{\\rm goal}P(U)]\\right|$ ，其中：$U_{\\rm goal}=U_{\\rm CZ}$、$d$ 为 $U_{\\rm goal}$ 的维度、$U$ 是系统的酉演化，投影后的 $P(U)$ 描述了投影在计算空间上的系统演化。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"minimum infidelity: {infidelity}\")\n",
    "gateJob.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们之前定义的系统是由两个三能级量子比特组成的。这表明该系统的时间演化算符是一个 $9\\times9$ 的矩阵。用户可以使用 `simulate()` 函数来模拟演化，系统演化后投影到计算子空间的矩阵 $P(U)$ 可以由函数 `project()` 得到："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = ham.simulate(job=gateJob)\n",
    "process2d = project(result.result[0][\"unitary\"], qubits, level, 2)\n",
    "print(\"The projected evolution P(U):\\n\", round(process2d, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "本教程介绍了使用量脉云服务实现 Controlled-Z 门。用户可以通过点击这个链接 [tutorial-cz-gate.ipynb](https://github.com/baidu/Quanlse/blob/main/Tutorial/CN/tutorial-cz-cn.ipynb) 跳转到此 Jupyter Notebook 文档相应的 GitHub 页面并且运行这个程序。我们鼓励用户尝试不同于本教程的参数值以获得最佳结果。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 参考\n",
    "\\[1\\] [Krantz, Philip, et al. \"A quantum engineer's guide to superconducting qubits.\" *Applied Physics Reviews* 6.2 (2019): 021318.](https://doi.org/10.1063/1.5089550)"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "6ad73c40f4f7e139e51b4243fd18c81784a68c09ce49361ba281b37d203f3e8e"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
